package com.example.mytestdemo.extensions

import android.annotation.SuppressLint
import android.app.Activity
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Build
import android.widget.ImageView
import androidx.annotation.DrawableRes
import androidx.fragment.app.FragmentActivity
import com.bumptech.glide.Glide
import com.bumptech.glide.RequestBuilder
import com.bumptech.glide.integration.webp.decoder.WebpDrawable
import com.bumptech.glide.integration.webp.decoder.WebpDrawableTransformation
import com.bumptech.glide.load.DecodeFormat
import com.bumptech.glide.load.Transformation
import com.bumptech.glide.load.model.GlideUrl
import com.bumptech.glide.load.model.LazyHeaders
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions.withCrossFade
import com.bumptech.glide.request.RequestOptions
import java.io.File

/**
 * imageView.load("https://www.weipaitang.com/logo.jpg")
 *
 * imageView.load("https://www.weipaitang.com/logo.jpg") {
 *      crossFade()
 *      circular()
 *      resize(100, 100)
 *      placeholder(R.drawable.placeholder)
 *      format(DecodeFormat.PREFER_ARGB_8888)
 *      options(any glide RequestOptions)
 *      options(any glide RequestOptions)
 *      options(any glide RequestOptions)
 *      ....
 * }
 *
 * @deprecated
 *
 */

fun ImageView.load(@DrawableRes res: Int?, config: Configuration.() -> Unit = {}) {
    loadFinally(this, Glide.with(this).load(res), config)
}

fun ImageView.load(uri: Uri?, config: Configuration.() -> Unit = {}) {
    loadFinally(this, Glide.with(this).load(uri), config)
}

fun ImageView.load(file: File?, config: Configuration.() -> Unit = {}) {
    loadFinally(this, Glide.with(this).load(file), config)
}

fun ImageView.load(bitmap: Bitmap?, config: Configuration.() -> Unit = {}) {
    loadFinally(this, Glide.with(this).load(bitmap), config)
}

fun ImageView.load(drawable: Drawable?, config: Configuration.() -> Unit = {}) {
    loadFinally(this, Glide.with(this).load(drawable), config)
}

@Deprecated("已废弃，请使用loadWebp")
fun ImageView.oldLoad(url: String?, config: Configuration.() -> Unit = {}) {
    try {
        if (context is FragmentActivity) {
            val attachAct = context as FragmentActivity
            if (assertActivityDestroyed(attachAct)) {
                return
            }
        } else if (context is Activity) {
            val attachAct = context as Activity
            if (assertActivityDestroyed(attachAct)) {
                return
            }
        }
        if (!url.isNullOrBlank() && url.startsWith("http")){
            try {
                val glideUrl = GlideUrl(url,LazyHeaders
                    .Builder()
                    .addHeader("image-info",this.context.javaClass.simpleName)
                    .build())
                loadFinally(this, Glide.with(this).load(glideUrl), config)
            }catch (e:Exception){
                loadFinally(this, Glide.with(this).load(url), config)
            }
        } else {
            loadFinally(this, Glide.with(this).load(url), config)
        }
    }catch (e:Exception){
        e.printStackTrace()
    }
}

fun ImageView.loadGlideUrl(model: GlideUrl?, config: Configuration.() -> Unit = {}) {
    loadFinally(this, Glide.with(this).load(model), config)
}

@SuppressLint("CheckResult")
private fun loadFinally(imageView: ImageView, builder: RequestBuilder<Drawable>, config: Configuration.() -> Unit = {}) {
    val configuration = Configuration().apply(config)
    if (configuration.crossFade) {
        builder.transition(withCrossFade())
    }
    if (configuration.circular) {
        builder.apply(RequestOptions.circleCropTransform())
    }
    if (configuration.width != null && configuration.height != null) {
        builder.apply(RequestOptions.overrideOf(configuration.width!!, configuration.height!!))
    }
    if (configuration.placeholderId > 0) {
        builder.apply(RequestOptions.placeholderOf(configuration.placeholderId))
    }
    if (configuration.errorId > 0) {
        builder.apply(RequestOptions.errorOf(configuration.errorId))
    }
    if (configuration.corner > 0) {
        builder.apply(RequestOptions.bitmapTransform(RoundedCorners(configuration.corner)))
    }
    builder.apply(RequestOptions().format(configuration.format))
    configuration.optionList.forEach { builder.apply(it) }
    builder.transformations.forEach { (classType, transformation) ->
        if (classType == Bitmap::class.java){
            try {
                val result = transformation as Transformation<Bitmap>?
                builder.optionalTransform(WebpDrawable::class.java, WebpDrawableTransformation(result))
            }catch (e:Exception){
                e.printStackTrace()
            }
        }
    }
    builder.into(imageView)
}

class Configuration {
    internal var crossFade = false
    internal var placeholderId = 0
    internal var errorId = 0
    internal var circular = false
    internal var width: Int? = null
    internal var height: Int? = null
    internal var corner = 0
    internal var format = DecodeFormat.PREFER_ARGB_8888
    internal val optionList = mutableListOf<RequestOptions>()

    fun crossFade() = apply {
        this.crossFade = true
    }

    fun circular() = apply {
        this.circular = true
    }

    fun corners(corner: Int) {
        this.corner = corner
    }

    fun placeholder(@DrawableRes placeholderId: Int) = apply {
        this.placeholderId = placeholderId
    }

    fun imgError(@DrawableRes errorId: Int) = apply {
        this.errorId = errorId
    }

    fun resize(width: Int, height: Int) = apply {
        this.width = width
        this.height = height
    }

    fun format(format: DecodeFormat) = apply {
        this.format = format
    }

    fun options(options: RequestOptions) = apply {
        optionList.add(options)
    }

}


@SuppressLint("ObsoleteSdkInt")
private fun assertActivityDestroyed(activity: Activity): Boolean {
    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && activity.isDestroyed
}